package cn.com.weshare.lock.lock;

/**
 * @author dujunguang
 * @description: TODO
 * @date: 2022/9/18 17:02
 **/
public class LockDcl {
    /**
     * volatile的作用是为了禁止指令重排
     * 原因在于某一个线程在执行到第一次检测,读取到的instance不为null时,instance的引用对象可能没有完成初始化.
     * new 一个对象的过程
     * 1、分配对象内存空间
     * 2、初始化对象，instance
     * 3、设置instance指向刚刚分配的内存地址，此时instance != null
     * <p>
     * 步骤2和步骤3不存在数据依赖关系，HP原则，而且无论重排前还是重排后程序执行的结果在单线程中并没有改变,因此这种重排优化是允许的.
     *
     * @date 2022/9/18 17:06
     */
    private static volatile LockDcl instance = null;

    private LockDcl() {
        System.out.println(Thread.currentThread().getName() + "\t 构造方法");
    }

    /**
     * 双重检测机制
     *
     * @return
     */
    public static LockDcl getInstance() {
        if (instance == null) {
            synchronized (LockDcl.class) {
                if (instance == null) {
                    instance = new LockDcl();
                }
            }
        }
        return instance;
    }

    public static void main(String[] args) {
        for (int i = 1; i <= 1000000; i++) {
            new Thread(() -> {
                LockDcl.getInstance();
            }, String.valueOf(i)).start();
        }
    }
}
